package com.eastfair.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.common.dao.AuthCodeUserMapper;
import com.eastfair.common.dto.AuthCodeUserDTO;
import com.eastfair.common.entity.AuthCode;
import com.eastfair.common.entity.AuthCodeUser;
import com.eastfair.common.service.AuthCodeService;
import com.eastfair.common.service.AuthCodeUserService;
import com.eastfair.common.vo.AuthCodeUserVO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 服务商对外授权码与用户关系
 * </p>
 *
 * @author dqq
 * @date 2023-02-14
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class AuthCodeUserServiceImpl extends SuperServiceImpl<AuthCodeUserMapper, AuthCodeUser> implements AuthCodeUserService {

    @Value("${com.eastfair.projectId}")
    private Long projectId;

    @Resource
    private AuthCodeService authCodeService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<AuthCodeUser> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(AuthCodeUser model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public List<AuthCodeUser> listAuthCodeUser(AuthCodeUserDTO query) {
        log.info("listAuthCodeUser - 查询授权码用户关系列表, authCodeDTO={}", query);
        QueryWrapper<AuthCodeUser> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(AuthCodeUser::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(StrUtil.isNotBlank(query.getAuthCode()), AuthCodeUser::getAuthCode, query.getAuthCode())
                .in(query.getAuthCodeList() != null && !query.getAuthCodeList().isEmpty(),
                        AuthCodeUser::getAuthCode, query.getAuthCodeList())
                .eq(StrUtil.isNotBlank(query.getAuthUserId()), AuthCodeUser::getAuthUserId, query.getAuthUserId())
        ;
        return list(queryWrapper);
    }

    @Override
    public List<AuthCodeUser> listByAuthUserId(String authUserId) {
        log.info("listByAuthUserId - 授权用户ID查询授权关系, authUserId={}", authUserId);
        AuthCodeUserDTO authCodeUserQuery = new AuthCodeUserDTO();
        authCodeUserQuery.setAuthUserId(authUserId);
        return listAuthCodeUser(authCodeUserQuery);
    }

    @Override
    public List<AuthCodeUserVO> listVOByAuthCode(String authCode) {
        AuthCodeUserDTO query = new AuthCodeUserDTO();
        query.setAuthCode(authCode);
        List<AuthCodeUser> list = listAuthCodeUser(query);
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list
                .stream()
                .map(authCodeUser -> BeanUtil.toBean(authCodeUser, AuthCodeUserVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public AuthCodeUser getByAuthUserIdAndAuthCode(String authUserId, String authCode) {
        AuthCodeUserDTO query = new AuthCodeUserDTO();
        query.setAuthUserId(authUserId);
        query.setAuthCode(authCode);
        List<AuthCodeUser> list = listAuthCodeUser(query);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R<Boolean> bindAuthCodeUser(AuthCodeUserDTO authCodeUserDTO) {
        log.info("bindAuthCodeUser - 外部用户与授权码绑定, authCodeUserDTO={}", authCodeUserDTO);
        ContextUtil.setProjectId(projectId);
        // 查询当前要绑定的邀请码
        AuthCode nowAuthCode = authCodeService.getByAuthCode(authCodeUserDTO.getAuthCode());
        // 授权码不存在
        if (nowAuthCode == null) {
            return R.result(1001, false, "授权码不存在");
        }
        // 授权码已过有效期
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(nowAuthCode.getValidStartTime()) || now.isAfter(nowAuthCode.getValidEndTime())) {
            return R.result(1002, false, "授权码不在有效期内，不可绑定");
        }
        if (!nowAuthCode.getExhibitionManageId().equals(authCodeUserDTO.getExhibitionManageId())) {
            return R.result(1004, false, "授权码不属于当前展会，请使用此展会的授权码");
        }
        // 查询用户已绑定的授权码列表
        List<AuthCodeUser> existAuthCodeUserList = listByAuthUserId(authCodeUserDTO.getAuthUserId());
        // 如果未绑定过授权码，则允许绑定
        if (existAuthCodeUserList == null || existAuthCodeUserList.isEmpty()) {
            return R.successDef(saveAuthCodeUser(authCodeUserDTO));
        }
        for (AuthCodeUser existAuthCodeUser: existAuthCodeUserList) {
            AuthCode existAuthCode = authCodeService.getByAuthCode(existAuthCodeUser.getAuthCode());
            if (existAuthCode.getAuthCode().equals(nowAuthCode.getAuthCode())) {
                return R.result(1003, false, "该用户已绑定该授权码");
            }
            // 如果有相同展会的授权关系，则先删除已有的授权关系
            if (existAuthCode.getExhibitionManageId().equals(nowAuthCode.getExhibitionManageId())) {
                removeByAuthCodeAndAuthUserId(existAuthCodeUser.getAuthCode(), existAuthCodeUser.getAuthUserId());
            }
        }
        return R.successDef(saveAuthCodeUser(authCodeUserDTO));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAuthCodeUser(AuthCodeUserDTO authCodeUserDTO) {
        log.info("saveAuthCodeUser - 保存用户授权码关系, authCodeUserDTO={}", authCodeUserDTO);
        AuthCodeUser authCodeUser = BeanUtil.toBean(authCodeUserDTO, AuthCodeUser.class);
        return save(authCodeUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAuthCodeUser(AuthCodeUserDTO authCodeUserDTO) {
        log.info("updateAuthCodeUser - 更新用户授权关系, authCodeUserDTO={}", authCodeUserDTO);
        AuthCodeUser authCodeUser = BeanUtil.toBean(authCodeUserDTO, AuthCodeUser.class);
        return updateById(authCodeUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateLastLoginTime(String authCodeUserId, String authCode) {
        log.info("updateLastLoginTime - 更新最后登录时间, authCodeUserId={}, authCode={}", authCodeUserId, authCode);
        AuthCodeUser authCodeUser = getByAuthUserIdAndAuthCode(authCodeUserId, authCode);
        if (authCode == null) {
            return false;
        }
        authCodeUser.setLastLoginTime(LocalDateTime.now());
        return updateById(authCodeUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByAuthCode(List<String> authCodeList) {
        log.info("removeByAuthCode - 授权码删除授权码用户关系, authCodeList={}", authCodeList);
        AuthCodeUserDTO query = new AuthCodeUserDTO();
        query.setAuthCodeList(authCodeList);
        List<AuthCodeUser> list = listAuthCodeUser(query);
        if (list == null || list.isEmpty()) {
            return true;
        }
        return removeByIdsOfLogic(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByAuthCodeAndAuthUserId(String authCode, String authUserId) {
        log.info("removeByAuthCodeAndAuthUserId - 根据用户ID与授权码删除授权关系, authCode={}, authUserId={}", authCode, authUserId);
        AuthCodeUserDTO query = new AuthCodeUserDTO();
        query.setAuthCode(authCode);
        query.setAuthUserId(authUserId);
        List<AuthCodeUser> list = listAuthCodeUser(query);
        if (list == null || list.isEmpty()) {
            return false;
        }
        return removeByIdsOfLogic(list);
    }
}
